package com.louzhu.gulimall.product.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.louzhu.common.constant.ProductConstant;
import com.louzhu.gulimall.product.dao.AttrAttrgroupRelationDao;
import com.louzhu.gulimall.product.dao.AttrGroupDao;
import com.louzhu.gulimall.product.dao.CategoryDao;
import com.louzhu.gulimall.product.entity.AttrAttrgroupRelationEntity;
import com.louzhu.gulimall.product.entity.AttrGroupEntity;
import com.louzhu.gulimall.product.entity.CategoryEntity;
import com.louzhu.gulimall.product.service.CategoryService;
import com.louzhu.gulimall.product.vo.AttrRespVo;
import com.louzhu.gulimall.product.vo.AttrVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.louzhu.common.utils.PageUtils;
import com.louzhu.common.utils.Query;

import com.louzhu.gulimall.product.dao.AttrDao;
import com.louzhu.gulimall.product.entity.AttrEntity;
import com.louzhu.gulimall.product.service.AttrService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;


@Service("attrService")
public class AttrServiceImpl extends ServiceImpl<AttrDao, AttrEntity> implements AttrService {

    @Autowired
    private AttrAttrgroupRelationDao relationDao;
    @Autowired
    private AttrGroupDao attrGroupDao;
    @Autowired
    private CategoryDao categoryDao;
    @Autowired
    private CategoryService categoryService;


    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<AttrEntity> page = this.page(
                new Query<AttrEntity>().getPage(params),
                new QueryWrapper<AttrEntity>()
        );

        return new PageUtils(page);
    }

    /**
     * 分页查询
     * @param params 查询条件
     * @param catelogId 分类ID
     * @param attrType 属性类别 base为规格参数 sale为销售属性
     * @return
     */
    @Override
    public PageUtils queryBaseAttrPage(Map<String, Object> params, Long catelogId, String attrType) {
        /*
        查询条件器中加入查询的属性类型
        前端传入的属性类型值 为 base 对应数据库的值 1 表示基本属性
        前端传入的属性类型值 为 sale 对应数据库的值 0 表示销售属性
         */
        QueryWrapper<AttrEntity> queryWrapper =
                new QueryWrapper<AttrEntity>().eq("attr_type","base".equalsIgnoreCase(attrType)?
                        ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode():ProductConstant.AttrEnum.ATTR_TYPE_SALE.getCode());

        /*
        如果分类ID不是0表示按指定分类查询，为0表示查询所有分类(注意此处catelogId的类型为Long)
         */
        if(catelogId != 0L){
            queryWrapper.eq("catelog_id",catelogId);
        }
        /*
        模糊查询关键字
         */
        String key = (String) params.get("key");
        if(!StringUtils.isEmpty(key)){
            queryWrapper.and((wrapper)->{
                wrapper.eq("attr_id",key).or().like("attr_name",key);
            });
        }

        /*
        正式查询满足条件的属性
         */
        IPage<AttrEntity> page = this.page(new Query<AttrEntity>().getPage(params),queryWrapper);
        PageUtils pageUtils = new PageUtils(page);
        List<AttrEntity> records = page.getRecords();

        /*
        查询出结果后结合分类名字，分组名字封装为AttrRespVo对象 （分类--属性--分组）
         */
        List<AttrRespVo> respVos = records.stream().map((attrEntity) -> {
            AttrRespVo attrRespVo = new AttrRespVo();
            BeanUtils.copyProperties(attrEntity,attrRespVo);
            /*
            设置分类名称、分组名称
             */
            // 根据属性ID查询出 属性-属性分组关联对象
            // 此处只查询基本属性也就是规格参数，销售属性没有分组只有分类
            if("base".equalsIgnoreCase(attrType)){
                AttrAttrgroupRelationEntity relationEntity =
                        relationDao.selectOne(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id",attrEntity.getAttrId()));
                if(null != relationEntity && null != relationEntity.getAttrGroupId()){
                    AttrGroupEntity attrGroupEntity = attrGroupDao.selectById(relationEntity.getAttrGroupId());
                    attrRespVo.setGroupName(attrGroupEntity.getAttrGroupName());
                }
            }
            CategoryEntity categoryEntity = categoryDao.selectById(attrEntity.getCatelogId());
            if(null != categoryEntity){
                attrRespVo.setCatelogName(categoryEntity.getName());
            }
            return attrRespVo;
        }).collect(Collectors.toList());

        pageUtils.setList(respVos);

        return pageUtils;
    }

    /**
     * 新增属性
     * @param attrVo
     */
    @Transactional
    @Override
    public void saveAttr(AttrVo attrVo) {
        AttrEntity attrEntity = new AttrEntity();
        // 实现两个Bean之间的属性对拷
        BeanUtils.copyProperties(attrVo,attrEntity);
        // 保存基本数据
        this.save(attrEntity);
        // 保存关联关系
        if(attrVo.getAttrType() == ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode()
                && attrVo.getAttrGroupId() != null){
            AttrAttrgroupRelationEntity relationEntity = new AttrAttrgroupRelationEntity();
            relationEntity.setAttrGroupId(attrVo.getAttrGroupId());
            relationEntity.setAttrId(attrEntity.getAttrId());

            relationDao.insert(relationEntity);
        }
    }

    /*
    根据ID获取属性详细信息
     */
    @Override
    public AttrRespVo getAttrInfo(Long attrId) {
        // 创建vo对象封装页面需要的数据
        AttrRespVo attrRespVo = new AttrRespVo();
        // 根据ID查询数据库实体类对象
        AttrEntity attrEntity = this.getById(attrId);
        // 属性拷贝
        BeanUtils.copyProperties(attrEntity,attrRespVo);

        /*
        查询分组信息
         */
        AttrAttrgroupRelationEntity attrAttrgroupRelationEntity =
                relationDao.selectOne(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attrId));
        if(null != attrAttrgroupRelationEntity){
            // 分组ID
            attrRespVo.setAttrGroupId(attrAttrgroupRelationEntity.getAttrGroupId());
            // 根据分组ID查询出分组名称
            AttrGroupEntity attrGroupEntity = attrGroupDao.selectById(attrAttrgroupRelationEntity.getAttrGroupId());
            if(null != attrGroupEntity){
                attrRespVo.setGroupName(attrGroupEntity.getAttrGroupName());
            }
        }

        /*
        查询分类信息
         */
        // 当前分类的ID
        Long catelogId = attrEntity.getCatelogId();
        // 查询到当前分类的全级分类ID数组
        Long[] paths = categoryService.finCatelogPath(catelogId);
        attrRespVo.setCatelogPath(paths);
        // 查询当前分类的名称
        CategoryEntity categoryEntity = categoryDao.selectById(catelogId);
        if(null != categoryEntity){
            attrRespVo.setCatelogName(categoryEntity.getName());
        }

        return attrRespVo;
    }

    /*
    修改
     */
    @Transactional
    @Override
    public void updateAttr(AttrVo attrVo) {
        /*
        完成基本的修改
         */
        AttrEntity attrEntity = new AttrEntity();
        BeanUtils.copyProperties(attrVo,attrEntity);
        this.updateById(attrEntity);
        /*
        修改分组管关联 一个属性对应一个分组
         */
        AttrAttrgroupRelationEntity attrAttrgroupRelationEntity = new AttrAttrgroupRelationEntity();
        attrAttrgroupRelationEntity.setAttrId(attrVo.getAttrId());
        attrAttrgroupRelationEntity.setAttrGroupId(attrVo.getAttrGroupId());

        /*
        查询当前属性-分组关联表中的记录，
        原则上一个属性对应一个分组，
        如果查询结果大于0表示本次操作为修改属性-分组关联关系
        如果结果为0 表示本次操作为新增关联关系
         */
        Integer count = relationDao.selectCount(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attrVo.getAttrId()));
        if(count>0){
            relationDao.update(attrAttrgroupRelationEntity,new UpdateWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attrVo.getAttrId()));
        }else {
            relationDao.insert(attrAttrgroupRelationEntity);
        }
    }

    /**
     * 根据分组ID查询关联的所有属性（基本属性）
     * @param attrgroupId
     * @return
     */
    @Override
    public List<AttrEntity> getRelationAttr(Long attrgroupId) {
        // 根据分组ID查询出所有的属性-分组关联表数据
        List<AttrAttrgroupRelationEntity> attrAttrgroupRelationEntities =
                relationDao.selectList(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_group_id", attrgroupId));
        // 获取所有的属性ID
        List<Long> attrIds = attrAttrgroupRelationEntities.stream().map((attr) -> {
            return attr.getAttrId();
        }).collect(Collectors.toList());
        // 排除null或者空结果集
        if(null == attrIds || attrIds.size() == 0){
            return null;
        }
        // 根据属性ID查询属性集合
        Collection<AttrEntity> attrEntities = this.listByIds(attrIds);
        return (List<AttrEntity>)attrEntities;
    }

    /**
     * 获取某个分类尚未关联的其他所有属性
     * @param params
     * @param attrgroupId
     * @return
     */
    @Override
    public PageUtils getNoRelationAttr(Map<String, Object> params, Long attrgroupId) {
        /*
        某个属性分组只能关联其所属三级分类下的属性
        某个属性分组只能关联其他属性分组没有关联的属性
         */

        // 查询当前分组对象
        AttrGroupEntity attrGroupEntity = attrGroupDao.selectById(attrgroupId);
        // 当前分组所属的三级分类ID
        Long catelogId = attrGroupEntity.getCatelogId();
        // 当前三级分类下的所有属性分组ID集合
        List<AttrGroupEntity> attrGroups = attrGroupDao.selectList(new QueryWrapper<AttrGroupEntity>().eq("catelog_id", catelogId));
        List<Long> collect = attrGroups.stream().map(item -> {
            return item.getAttrGroupId();
        }).collect(Collectors.toList());
        // 查询这些分组已经关联的属性
        List<AttrAttrgroupRelationEntity> attrAttrgroupRelationEntities =
                relationDao.selectList(new QueryWrapper<AttrAttrgroupRelationEntity>().in("attr_group_id", collect));
        List<Long> attrIds = attrAttrgroupRelationEntities.stream().map(item -> {
            return item.getAttrId();
        }).collect(Collectors.toList());
        // 从当前分类下的所有属性中，除去已被其他分组关联的属性，就是可供当前属性分组选择关联的属性
        QueryWrapper<AttrEntity> queryWrapper = new QueryWrapper<AttrEntity>()
                .eq("catelog_id", catelogId)
                .eq("attr_type", ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode());
        if(null != attrIds && attrIds.size()>0){
            queryWrapper.notIn("attr_id",attrIds);
        }
        // 加入请求参数中的模糊查询条件
        String key = (String) params.get("key");
        if(!StringUtils.isEmpty(key)){
            queryWrapper.and((w)->{
                w.eq("attr_id",key).or().like("attr_name",key);
            });
        }
        // 携带查询条件进行分页查询
        IPage<AttrEntity> page = this.page(new Query<AttrEntity>().getPage(params), queryWrapper);
        PageUtils pageUtils = new PageUtils(page);
        return pageUtils;
    }

    /**
     * 过滤 需要检索的 attrId
     * @param attrIds 被过滤的 attrId 集合
     * @return 需要检索的 attrId 集合
     */
    @Override
    public List<Long> filterAddrId(List<Long> attrIds) {
        return baseMapper.filterAddrId(attrIds);
    }

}